package com.yzs.base.base

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.gyf.immersionbar.ImmersionBar
import com.jeremyliao.liveeventbus.core.Observable
import com.yzs.base.ui.dialog.LoadingDialog
import java.util.concurrent.atomic.AtomicBoolean


/**
 *    author : yzs
 *    date   : 2022/1/1211:50
 *    desc   : 基础类封装
 */
abstract class BaseFragment : Fragment() {

    lateinit var mContext: Context
    lateinit var mActivity: AppCompatActivity

    private val visibleAtomic = AtomicBoolean(false)

    private var mLoadingDialog: LoadingDialog? = null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        this.mContext = context
        mActivity = context as AppCompatActivity
        // 必须要在 Activity 与 Fragment 绑定后，
        // 因为如果 Fragment 可能获取的是 Activity 中 ViewModel
        initViewModel()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 设置状态栏
        statusBarDarkFont(true)
        return initViewBinding()?.root ?: inflater.inflate(getLayoutId(), container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        init(view, savedInstanceState)
        // observe 一定要在初始化最后，因为 observe 会收到黏性事件，随后对 ui 做处理
        observe()
        onClick()
    }


    override fun onResume() {
        super.onResume()
        visibleAtomic.set(true)
        onVisible()
    }

    override fun onPause() {
        super.onPause()
        visibleAtomic.set(false)
        onHidden()
    }

    override fun onDestroyView() {
        dismissLoadingDialog()
        visibleAtomic.set(false)
        super.onDestroyView()
    }

    protected fun showLoadingDialog(canCancel: Boolean = false) {
        if (!this.isAdded) return
        if (mLoadingDialog == null) mLoadingDialog = LoadingDialog(mContext, canCancel)
        mLoadingDialog?.let { if (!it.isShowing) it.show() }
    }

    protected open fun dismissLoadingDialog() {
        mLoadingDialog?.let { if (it.isShowing) it.dismiss() }
    }

    /**
     * 可交互时回调 （和 activity 保持方法一致）
     */
    open fun onVisible() {
    }

    /**
     * 不可交互时回调 （和 activity 保持方法一致）
     */
    open fun onHidden() {
    }

    protected fun isPageVisible(): Boolean {
        return visibleAtomic.get()
    }

    /**
     * 使用 viewBinding 初始布局
     */
    open fun initViewBinding(): ViewBinding? {
        return null
    }

    /**
     * 初始化入口
     */
    abstract fun init(view: View, savedInstanceState: Bundle?)

    /**
     * 获取layout布局
     */
    abstract fun getLayoutId(): Int

    /**
     * 初始化viewModel
     * 之所以没有设计为抽象，是因为部分简单activity可能不需要viewModel
     * observe同理
     */
    open fun initViewModel() {}

    /**
     * 注册观察者
     */
    open fun observe() {}

    /**
     * 点击事件
     */
    open fun onClick() {}

    /**
     * 通过 activity 获取 viewModel，跟随 activity 生命周期
     */
    fun <T : ViewModel> getActivityViewModel(modelClass: Class<T>): T {
        return ViewModelProvider(
            requireActivity().viewModelStore,
            defaultViewModelProviderFactory
        ).get(modelClass)
    }

    /**
     * 通过 fragment 获取 viewModel，跟随 fragment 生命周期
     */
    protected open fun <T : ViewModel> getFragmentViewModel(modelClass: Class<T>): T {
        return ViewModelProvider(this, defaultViewModelProviderFactory).get(modelClass)
    }

    /**
     * 扩展用于liveData便捷写法的函数
     * [block] liveData 对象，响应 change 变化的逻辑块
     */
    protected inline fun <T : Any> LiveData<T>.observeKt(crossinline block: (T?) -> Unit) {
        this.observe(this@BaseFragment, Observer { block(it) })
    }

    /**
     * 扩展用于 liveData 便捷写法的函数
     * [block] liveData 对象，响应 change 变化的逻辑块
     * 认为 不为 null 的情况
     */
    protected inline fun <T : Any> LiveData<T>.observeKtNoNull(crossinline block: (T) -> Unit) {
        this.observe(this@BaseFragment, Observer { block(it) })
    }

    protected inline fun <T> Observable<T>.register(crossinline block: (T) -> Unit) {
        this.observe(this@BaseFragment, { block(it) })
    }

    /**
     * 如果之前有消息发送，可以在注册时收到消息（消息同步）
     */
    protected inline fun <T> Observable<T>.registerSticky(crossinline block: (T) -> Unit) {
        this.observeSticky(this@BaseFragment, { block(it) })
    }

//    protected inline fun <T> Observable<T>.registerForever(crossinline block: (T) -> Unit) {
//        val observer = Observer<T> { t -> block(t) }
//        this.observeForever(observer)
//    }


    /**
     * 设置状态栏字体颜色
     * [isDarkFont] true:深色  false:浅色
     */
    protected fun statusBarDarkFont(isDarkFont: Boolean) {
        ImmersionBar.with(this).statusBarDarkFont(isDarkFont).init()
    }

}